package cn.lijiajia3515.starter.web.autoconfigure.exception;

import cn.lijiajia3515.cairo.core.business.ParamBusiness;
import cn.lijiajia3515.cairo.core.result.BusinessResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 参数校验异常 统一处理器
 */
@Slf4j
@RestControllerAdvice(annotations = RestController.class)
@Configuration(proxyBeanMethods = false)
@Order(101)

public class CairoValidationExceptionRestHandlerAutoConfiguration {

	@ExceptionHandler(BindException.class)
	public ResponseEntity<BusinessResult<List<String>>> bindExceptionHandler(BindException e) {
		List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
		List<String> messages = fieldErrors.stream()
			.map(DefaultMessageSourceResolvable::getDefaultMessage)
			.collect(Collectors.toList());

		BusinessResult<List<String>> body = BusinessResult.<List<String>>builder().business(ParamBusiness.NotValid).data(messages).build();

		return ResponseEntity.status(HttpStatus.BAD_REQUEST)
			.body(body);
	}

	// <2> 处理 json 请求体调用接口校验失败抛出的异常
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public ResponseEntity<BusinessResult<List<String>>> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
		List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
		List<String> messages = fieldErrors.stream()
			.map(DefaultMessageSourceResolvable::getDefaultMessage)
			.collect(Collectors.toList());

		BusinessResult<List<String>> body = BusinessResult.<List<String>>builder().business(ParamBusiness.NotValid).data(messages).build();

		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
	}

	// <3> 处理单个参数校验失败抛出的异常
	@ExceptionHandler(ConstraintViolationException.class)
	public ResponseEntity<BusinessResult<List<String>>> constraintViolationExceptionHandler(ConstraintViolationException e) {
		Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
		List<String> messages = constraintViolations.stream()
			.map(ConstraintViolation::getMessage)
			.collect(Collectors.toList());

		BusinessResult<List<String>> body = BusinessResult.<List<String>>builder().business(ParamBusiness.NotValid).data(messages).build();

		return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body);
	}

}
